647. 回文子串

647. 回文子串

Similar Question

Solution Tips

方案一: 中心扩展法

分别以奇数和偶数为中心

function countSubstrings(s: string): number {
    const length: number = s.length;
    let resCount: number = 0;
    for (let i = 0; i < length; i++) {
        resCount += expandRange(s, i, i);
        resCount += expandRange(s, i, i + 1);
    }
    return resCount;
};
function expandRange(s: string, left: number, right: number): number {
    let palindromeNum: number = 0;
    while (
        left >= 0 && right < s.length &&
        s[left] === s[right]
    ) {
        palindromeNum++;
        left--;
        right++;
    }
    return palindromeNum;
}

奇数、偶数二合一, 感觉不好理解

const countSubstrings = (s) => {
    const strLen = s.length;
    let numOfPalindromicStr = 0;

    for(let i = 0; i < 2 * strLen - 1; i++) {
        let left = Math.floor(i/2);
        let right = left + i % 2;

        while(left >= 0 && right < strLen && s[left] === s[right]){
            numOfPalindromicStr++;
            left--;
            right++;
        }
    }

    return numOfPalindromicStr;
}

方案二: 中心扩展法的动态规划表示

var countSubstrings = function(s) {
    // 关键就是如何拆解出子问题, 因为回文串不能只看一个方向的
    // 子串是回文串, 要在两头都加入相同的字符才能继续构成子串
    // 难道这就是中心扩展法?
    // dp[i][j] 表示以 i 为中心, 向两边扩展 j 个字符, 是否是回文串
    // 插入空位, 处理偶数 case
    s = s.split('').join(' ');
    const half = Math.floor(s.length / 2);
    const dp = Array.from({ length: half });
    // 所有的 dp[i][0] 都为 true , 因为单个字符一定是回文串
    // 如果要应付偶数的情况, 那还得从空位开始扩展才行, 如果总是从单个字符开始扩展就只能处理奇数个字符
    let res = 0;
    for (let i = 0; i < s.length; i++) {
        for (let j = 0; j <= half; j++) {
            // j > 0
            const l = i - j;
            const r = i + j;
            if (j === 0) {
                dp[j] = true;
            }
            else {
                // l和r都在索引范围内, 并且不同为空串
                if (l >= 0 && r < s.length) {
                    // 空间复杂度太高了, 只依赖一行的, 一个行就够了
                    dp[j] = dp[j - 1] && s[l] === s[r];
                }
                else {
                    dp[j] = false;
                }
            }
            if (dp[j] && s[l] !== ' ' && s[r] !== ' ') {
                // slice i+-j
                const sub = s.slice(i - j, i + j + 1);
                sub !== ' ' && res++
            }
        }
    }

    return res;
};